package host;

import java.util.HashMap;
import java.util.Vector;

import datatypes.BluetoothDeviceAddress;
import datatypes.Connection;
import datatypes.Host;
import datatypes.HostDescription;
import datatypes.ScenarioDescription;

public class HostList {

	private HashMap<String, Host> activeHosts = new HashMap<String, Host>();
	private HashMap<String, Host> passiveAvailableHosts = new HashMap<String, Host>();

	private HashMap<String, Vector<Connection>> activeConnections = new HashMap<String, Vector<Connection>>();

	public void build(ScenarioDescription scenDesc) {
		Vector<HostDescription> tmp = (Vector<HostDescription>) scenDesc.getHosts().clone();
		for (int i = 0; i < tmp.size(); i++) {
			tmp.get(i).getHost().getRoutingSocket();
			tmp.get(i).getHost().getDiscoverySocket();
			if (tmp.get(i).getHost().isActive()) {
				activeHosts.put(tmp.get(i).getHost().getBd_Addr().getAddress(), tmp.get(i).getHost());
			} else {
				passiveAvailableHosts.put(tmp.get(i).getHost().getBd_Addr().getAddress(), tmp.get(i).getHost());
			}
		}
	}

	private void activateHost(Host host) {
		activeHosts.put(host.getBd_Addr().getAddress(), host);
		passiveAvailableHosts.remove(host.getBd_Addr().getAddress());
	}

	public void activateHost(BluetoothDeviceAddress host) {
		if (activeHosts.get(host.getAddress()) == null){
			activeHosts.put(host.getAddress(), (Host) (passiveAvailableHosts.get(host.getAddress())));
			passiveAvailableHosts.remove(host.getAddress());			
		}
	}

	private void deactivateHost(Host host) {
		if (passiveAvailableHosts.get(host.getBd_Addr().getAddress()) == null){
			passiveAvailableHosts.put(host.getBd_Addr().getAddress(), host);
			activeHosts.remove(host.getBd_Addr().getAddress());			
		}
	}

	public void deactivateHost(BluetoothDeviceAddress host) {
		if (passiveAvailableHosts.get(host.getAddress()) == null){
			passiveAvailableHosts.put(host.getAddress(), (Host) (activeHosts.get(host.getAddress())));
			activeHosts.remove(host.getAddress());			
		}
	}

	public Host getHost(BluetoothDeviceAddress bd_addr) {
		if (this.activeHosts.get(bd_addr.getAddress()) == null) {
			return this.passiveAvailableHosts.get(bd_addr.getAddress());
		}
		return this.activeHosts.get(bd_addr.getAddress());
	}

	public HashMap<String, Host> getActiveHosts() {
		return activeHosts;
	}

	public HashMap<String, Host> getPassiveAvailableHosts() {
		return passiveAvailableHosts;
	}

	// CONNECTION ADMINISTRATION
	public void addConnection(BluetoothDeviceAddress host, Connection con) {
		Vector<Connection> tmp = activeConnections.get(host.getAddress());
		if (tmp != null) {
			tmp.add(con);
		} else {
			tmp = new Vector<Connection>();
			tmp.add(con);
			activeConnections.put(host.getAddress(), tmp);
		}
	}

	public void removeConnection(BluetoothDeviceAddress host, BluetoothDeviceAddress otherPeer) {
		Vector<Connection> tmp = activeConnections.get(host.getAddress());
		if (tmp != null) {
			for (Connection con : tmp) {
				if (con.getConnectedPeer() != null && con.getConnectedPeer().getAddress().equals(otherPeer.getAddress())) {
					tmp.remove(con);
					break;
				}
			}
		}
	}

	public Vector<BluetoothDeviceAddress> getConnectionsTillTimeStamp(BluetoothDeviceAddress host, int timeStamp) {
		Vector<BluetoothDeviceAddress> tmp = new Vector<BluetoothDeviceAddress>();
		if (this.activeConnections.get(host.getAddress()) != null) {
			for (Connection con : this.activeConnections.get(host.getAddress())) {
				if (con.getTimeStamp() <= timeStamp) {
					tmp.add(con.getConnectedPeer());
				}
			}
		}
		return tmp;
	}

	public boolean isFreshPaired(BluetoothDeviceAddress host1, BluetoothDeviceAddress host2, int timeStamp) {
		Vector<BluetoothDeviceAddress> tmp = new Vector<BluetoothDeviceAddress>();
		if (this.activeConnections.get(host1.getAddress()) != null) {
			for (Connection con : this.activeConnections.get(host1.getAddress())) {
				if (con.getTimeStamp() == timeStamp) {
					tmp.add(con.getConnectedPeer());
				}
			}
		}
		for (BluetoothDeviceAddress add: tmp){
			if (add.getAddress().equals(host2.getAddress())){
				return true;
			}
		}
		return false;
	}

	public Vector<BluetoothDeviceAddress> getConnections(BluetoothDeviceAddress host) {
		Vector<BluetoothDeviceAddress> tmp = new Vector<BluetoothDeviceAddress>();
		for (Connection con : this.activeConnections.get(host.getAddress())) {
			tmp.add(con.getConnectedPeer());
		}
		return tmp;
	}
}
